import httpStreamService from './stream';
import httpService from './request';
import http from '@ohos.net.http';
import { fileManager } from '../utils/fileUtils';
import { getP, setP } from '../utils/GlobalContext';
import { promptAction } from '@kit.ArkUI';
import { LMreply } from '../utils/taskGraphInterface';

const TAG: string = "_:_"
const GENERATION_URL =
  "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-4.0-8k-latest?access_token=24.67ad70c8bd6e5aefb1fe2071dfa32a82.2592000.1741658810.282335-116263096"

export default class LLMmanager {
  private dir = ""
  private f1 = null
  private filename
  private result: string = ''
  private requestOptions: http.HttpRequestOptions = {}
  private mode = ""

  constructor(dir = "", filename = "", mode = "") { //mhc: multiple_round help_with_file_storing clear_previous
    this.mode = mode
    this.dir = dir
    this.filename = filename
    this.f1 = new fileManager(this.dir, this.filename)
    if (this.mode.includes("c")) {
      this.f1.clear()
    }
  }

  textToJson() {
    let TAG = "_:_textToJson"
    console.log(TAG, "entered")
    let Json = {
      "messages": [
        {
          "role": "user",
          "content": "请充分利用MarkDown的多样输出格式,写出可以直接被渲染的MarkDown回复"
        },
        {
          "role": "assistant",
          "content": "好的。"
        }],
      "disable_search": false,
      "enable_citation": true,
      "stream": true
    }
    let list = this.f1.readlist()
    for (let i = 0; i < list.length; i++) {
      let role = ""
      if (i % 2 == 0) {
        role = "user"
      } else {
        role = "assistant"
      }
      let message = {
        "role": role,
        "content": list[i]
      }
      if (list.length - i < 10) {
        Json["messages"].push(message)
      }
    }
    let cnt = 0
    console.log("________________start textToJson________________")
    for (let message of Json["messages"]) {
      console.log(TAG, String(cnt++), JSON.stringify(message))
    }
    console.log("________________start textToJson________________")
    return Json
  }

  InitParam(jsonobj) {
    this.requestOptions = {
      method: http.RequestMethod.POST,
      header: [{
        'Content-Type': 'application/json',
      }],
      extraData: JSON.stringify(jsonobj),
    }
  }

  async getHttpResult(jsonobj) {
    this.InitParam(jsonobj)
    return await httpService.requestMain(GENERATION_URL, this.requestOptions, (response) => {
      return this.parseResult(response)
    })
  }

  parseResult(result) {
    let TAG = "_:_[parseResult]"
    if (result.includes("error_msg")) {
      promptAction.showToast({
        "message": result, "duration": 5000
      })
    }
    try {
      let listresult = result.split("data:")
      listresult.shift()
      let str = ""
      for (let json of listresult) {
        try {
          str += JSON.parse(json)["result"]
        } catch (e) {
          console.log(TAG, "jsonparse err ", e, "at", json)
        }
      }
      return str
    } catch (e) {
      console.log(TAG, "parseResult", e)
      return result
    }
  }

  getHttpStreamResult(jsonobj, callback: (result: string) => void) {
    this.InitParam(jsonobj);
    httpStreamService.onDataReceive(callback);
    httpStreamService.requestHttp(GENERATION_URL, this.requestOptions).then((data: number) => {
      console.info(TAG, "requestInStream OK!" + JSON.stringify(data));
    }).catch((err: Error) => {
      console.info(TAG, "requestInStream ERROR : err = " + JSON.stringify(err));
      promptAction.showToast({
        message: "requestInStream ERROR : err = " + JSON.stringify(err)
      })
    });
  }

  parseSingle(data) {
    let TAG = "_:_getP_s__"
    try {
      // console.log(TAG,"data.len=",data.length,"origData=",data)
      // console.log(TAG,"no|n data.len=",data.replace(/\n/g,"").length,"no|n data=",data.replace(/\n/g,""))
      let pdata = JSON.parse(data)
      console.log(TAG, "parse success", pdata["result"], pdata["is_end"],data)
      let indexParams = getP()
      if (pdata["result"] == undefined && pdata["is_end"] == undefined) {
        indexParams.LLMss += "请检查网络连接或token是否过期 STREAMING_END"
        setP(indexParams)
      } else {
        indexParams.LLMss += pdata["result"]
        setP(indexParams)
      }
      if (pdata["is_end"]) {
        let indexParams = getP()
        if (this.mode.includes("h") && this.mode.includes("m")) {
          this.f1.write(indexParams.LLMss, 1)
        }
        indexParams.LLMss += "STREAMING_END"
        setP(indexParams)
      }
      return pdata
    } catch (e) {
      console.error(TAG, "error", JSON.stringify(e))
      return {
        "is_end": false, "result": ""
      }
    }
  }

  parseStreamResult(data) {
    let TAG = "_:_getPdata"
    // console.log(TAG,"data.len=",data.length,"origData=",data)
    // console.log(TAG,"no|n data.len=",data.replace(/\n/g,"").length,"no|n data=",data.replace(/\n/g,""))
    let datas = data.split("data: ")
    for (let idata of datas) {
      if (idata.trim().replace(/\n/g, "") != "") {
        this.parseSingle(idata)
      }
    }
  }

  async askLLMss(infoPrompt: string = ""): Promise<any> {
    let TAG = "_:_askLLMss"
    try {
      console.log(TAG, "askLLMss entered")
      this.getHttpStreamResult(
        this.mhcTextToJson(infoPrompt)
        , (data) => {
        return this.parseStreamResult(data)
      })
      return this.result
    } catch (e) {
      console.error(TAG, JSON.stringify(e))
      return JSON.stringify(e)
    }
  }

  mhcTextToJson(infoPrompt: string) {
    let jsonobj = {}
    if (!this.mode.includes("m")) {
      jsonobj = {
        "messages": [
          {
            "role": "user",
            "content": infoPrompt
          }
        ],
        "disable_search": false,
        "enable_citation": false,
        "stream": true
      }
    }
    if (this.mode.includes("h")) {
      this.f1.write(infoPrompt, 0)
    }
    if (this.mode.includes("m")) {
      jsonobj = this.textToJson()
    }
    return jsonobj
  }

  async askLLM(infoPrompt: string): Promise<string> {
    let jsonobj = this.mhcTextToJson(infoPrompt)
    let str = await this.getHttpResult(jsonobj)
    if (this.mode.includes("h") && this.mode.includes("m")) {
      this.f1.write(str, 1)
    }
    return str
  }

  async askLLMj(infoPrompt): Promise<LMreply | undefined> {
    let datam = await this.askLLM(infoPrompt)
    try {
      console.log("_:Raw full reply", datam)
      datam = datam.replace("```json", "")
        .replace("```", "")
        .replace(/\\n/g, "")
        .replace(/\s/g, " ")
        .match(/\{.*\}/)[0]
      console.info('Result replaced_:' + datam);
      let jdatam = JSON.parse(datam) as LMreply
      console.error('Result parsed _:_' + jdatam + JSON.stringify(jdatam));
      return jdatam
    } catch (e) {
      console.error(TAG, "error calling or parsing", JSON.stringify(e), datam.replace(/\n/g, ""))
      return undefined
    }
  }
}
